<?php

class VacServicePage extends Page
{

}

class VacServicePage_Controller extends Page_Controller
{
    private static $allowed_actions = array(
        "VacNews",
        "VacLogin",
        "VacCreateCode",
        "VacVerifyCode",
        "VacUpload",
        "VacGetQR"
    );

    public function index()
    {
        // Redirect user back to homepage if no action requested.
        return $this->redirect("/");
    }

    public function VacNews()
    {
        $this->ResidentNews = ResidentNews::get()->where("NewsStatus = '" . Globals::STATUS_ACTIVE . "' AND Expires > NOW() AND StartOn <= NOW()")->sort("StartOn DESC, ID DESC")->limit(10);
        return $this->renderWith(array("VacResidentNews"));
    }

    public function VacLogin()
    {
        $result = 0;
        $message = null;
        $token = null;
        $username = $this->request->requestVar("username");
        $password = $this->request->requestVar("password");

        if (!$username || !$password) {
            // Missing post data.
            $message = "Missing required parameters: username or password.";
        } else {
            $resident = Resident::get()->find("Username", $username);

            if ($resident) {
                // User found. Check account status and password.
                $valid = $resident->checkPassword($password);

                if ($valid->valid()) {
                    // Check user is logged in
                    $vacLogin = VacLogin::get()->filter(
                        array(
                            "ResidentID" => $resident->ID
                        )
                    )->first();

                    if ($vacLogin) {
                        // Retrieve existing login session as token.
                        $token = $vacLogin->LoginToken;
                    } else {
                        // Create login session as token.
                        $key = rand(1111, 9999);
                        $retry = false;

                        do {
                            $token = md5($username . "&$*32" . $password . "20$~*" . SS_Datetime::now() . $key);

                            // Check token is already in use or not.
                            $exists = VacLogin::get()->filter(
                                array(
                                    "LoginToken" => $token
                                )
                            )->first();

                            // Record is not null, which means token is already in use.
                            $retry = (!is_null($exists));
                        } while ($retry);

                        $vacLogin = new VacLogin();
                        $vacLogin->LoginToken = $token;
                        $vacLogin->ResidentID = $resident->ID;
                        $vacLogin->write();
                    }

                    $result = 1;
                    $message = "Login success.";
                } else {
                    $message = $valid->message();
                }
            } else {
                // User not exists.
                $message = "Invalid username or password.";
            }
        }

        return $this->responseJson($result, $message, array("token" => $token));
    }

    public function VacCreateCode()
    {
        $result = 0;
        $message = null;

        if ($this->isTokenValid(null, true, $vacLogin)) {
            $tagCode = str_pad(rand(0, 999999), 6, "0", STR_PAD_LEFT);
            $retry = false;

            do {
                $vacTag = VacTag::get()->filter(
                    array(
                        "TagCode" => $tagCode,
                        "ResidentID" => $vacLogin->ResidentID
                    )
                )->first();

                if ($vacTag && $vacTag->isTagValid(false)) {
                    // Tag code already in use.
                    // Re-generate tag code and retry checking.
                    $tagCode = str_pad(rand(0, 999999), 6, "0", STR_PAD_LEFT);
                    $retry = true;
                } else {
                    // Tag code not in use, exit checking.
                    $retry = false;
                }
            } while ($retry);

            $vacTag = new VacTag();
            $vacTag->TagCode = $tagCode;
            $vacTag->VehicleNo = $this->request->requestVar("vehicle_no");
            $vacTag->TagStatus = Globals::STATUS_ACTIVE;
            $vacTag->Expires = $vacTag->getExpiryDatetime();
            $vacTag->ResidentID = $vacLogin->ResidentID;
            $vacTag->generateQRFile();
            $vacTag->write();

            $QRUrl = Globals::PROJECT_DOMAIN . "/vac-service/VacGetQR?qr=" . $vacTag->QRFile()->Name;

            $result = 1;
            $message = "Code created successfully.";
        } else {
            $message = "Invalid token.";
        }

        return $this->responseJson($result, $message, array(
            "code" => $vacTag->TagCode,
            "expire_on" => $vacTag->Expires,
            "qr_url" => $QRUrl
        ));
    }

    public function VacVerifyCode()
    {
        $result = 0;
        $message = null;

        $tagCode = $this->request->requestVar("code");
        $vehicleNo = $this->request->requestVar("vehicle_no");
        $checkVehicleNo = ($this->request->requestVar("cv") == "1" ? true : false);
        $deactivateOnVerify = ($this->request->postVar("nu") == "1" ? false : true);

        if (!$tagCode) {
            // Missing post data.
            $message = "Missing required parameters: code.";
        } else {
            $vacTag = VacTag::get()->filter(
                array(
                    "TagCode" => $tagCode
                )
            )->first();

            if ($vacTag) {
                // Tag found.
                $tagStatus = ""; // Reference for tag code status.
                $vacTag->isTagValid($deactivateOnVerify, true, $tagStatus);

                if ($tagStatus == Globals::STATUS_ACTIVE) {
                    if ($checkVehicleNo) {
                        // Check for vehicle no.
                        if ($vacTag->VehicleNo == $vehicleNo) {
                            // Vehicle no. is not match.
                            $result = 1;
                            $message = "Code is valid";
                        } else {
                            $message = "Invalid vehicle number.";
                        }
                    } else {
                        $result = 1;
                        $message = "Code is valid.";
                    }
                } elseif ($tagStatus == Globals::STATUS_EXPIRED) {
                    $message = "Code is expired.";
                } else {
                    $message = "Invalid code.";
                }
            } else {
                $message = "Invalid code.";
            }
        }

        return $this->responseJson($result, $message);
    }

    public function VacGetQR()
    {
        $filename = $this->request->requestVar("qr");

        if ($filename) {
            $file = File::get()->filter(
                array(
                    "Name" => $filename
                )
            )->first();

            if ($file) {
                $filePath = BASE_PATH . "/assets/qr_codes/" . $filename;

                if ($this->request->requestVar("dl") == "1") {
                    // Download QR image.
                    return SS_HTTPRequest::send_file(file_get_contents($filePath), $filename);
                } else {
                    // Show QR image on web page.
                    $imgData = base64_encode(file_get_contents($filePath));
                    $this->Content = '<img src="data: png' . ";base64," . $imgData . '" />';
                    return $this->renderWith("BlankPage");
                }
            }
        }

        return $this->httpError(404);
    }

    public function VacUpload()
    {
        $result = 0;
        $message = null;

        if ($this->isTokenValid(null, true, $vacLogin)) {
            $photoFile = $_FILES["upload"];
            $photoMessage = $this->request->requestVar("message");

            if ($photoFile && $photoMessage && strlen($photoMessage)) {
                $upload = new Upload();
                $upload->setReplaceFile(false);

                if ($upload->load($photoFile, "/Uploads/resident_camera/")) {
                    // Upload success.
                    $vacPhotoUpload = new VacPhotoUpload();
                    $vacPhotoUpload->Message = $photoMessage;
                    $vacPhotoUpload->PhotoStatus = Globals::STATUS_UNREAD;
                    $vacPhotoUpload->ResidentID = $vacLogin->ResidentID;
                    $vacPhotoUpload->PhotoFileID = $upload->getFile()->ID;
                    $vacPhotoUpload->write();

                    $result = 1;
                    $message = "File uploaded successfully.";
                    $fileUrl = Globals::PROJECT_DOMAIN . "/vac-service/VacGetUpload?f=" . $upload->getFile()->Name;
                } else {
                    // Upload failed.
                    $message = "Upload file failed.";
                }
            } else {
                // Missing required data.
                $message = "Missing required parameters: file or message.";
            }
        } else {
            $message = "Invalid token.";
        }

        return $this->responseJson($result, $message, array(
            "f_url" => $fileUrl
        ));
    }

    public function getRequestToken()
    {
        return $this->request->requestVar("token");
    }

    public function isTokenValid($token = null, $checkAccountStatus = true, &$refModel)
    {
        if ($token == null) {
            $token = $this->getRequestToken();
        }

        if ($token != null) {
            $vacLogin = VacLogin::get()->filter(
                array(
                    "LoginToken" => $token
                )
            )->first();

            if ($vacLogin) {
                // Token found.
                $refModel = $vacLogin;

                if ($checkAccountStatus) {
                    // Check account status.
                    return $vacLogin->Resident()->canLogIn()->valid();
                } else {
                    // No need to check account status, done here.
                    return true;
                }
            }
        }

        return false;
    }

    public function responseJson($result = 0, $message = null, $data = null)
    {
        $arr = array(
            "result" => $result,
            "message" => $message
        );

        if (is_array($data)) {
            $arr = array_merge($arr, $data);
        }

        return json_encode($arr);
    }
}